package org.vectrics.skill;


import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.log4j.Logger;
import org.vectrics.SystemException;
import org.vectrics.VectricsException;
import org.vectrics.common.tree.TreeHelper;
import org.vectrics.recruiter.RecruitServiceLocator;



public abstract class SkillRatingSet {
	private transient static Logger log = Logger.getLogger(SkillRatingSet.class);
	
	HashSet skillRatings = new HashSet();
	UserEvaluation evaluation  = null;
	
    protected abstract SkillRating createSkillRating(Skill skill);
    
    public void addAll(Collection ratings) {
    	skillRatings.addAll(ratings);
    }
    
    public SkillRating findSkillRating(Skill skill) {
    	return(this.findSkillRating(skill.getCode()));
    }
    
    public SkillRating findSkillRating(String skillCode) {
    	SkillRating found = null;
    	try {
	    	Iterator iter = skillRatings.iterator();
	    	while ((found == null) && (iter.hasNext())) {
	    		SkillRating rating = (SkillRating)iter.next();
	    		if (rating == null) {
	    			throw new VectricsException("Unexpected condition in findSkillRating - rating in rating set was null");
	    		}
	    		if (rating.getSkill() == null) {
	    			throw new VectricsException(
	    					"Unexpected condition in findSkillRating - rating had null skill - rating.  Rating skill code = " + rating.getSkill().getCode());
	    		}
	    		if (rating.getSkill().getCode().equals(skillCode)) {
	    			found = rating;
	    		}
	    	}
    	}
    	catch (Exception ex) {
    		throw new SystemException("Exception in findSkillRating()", ex);
    	}
    	return(found);
    }
    
    
    public void clearSkillBranch(Skill skillToRemove) throws VectricsException {
    	log.debug("clearSkillBranch() - skillToRemove = " + skillToRemove.getCode());
    	HashSet removeList = new HashSet();
    	Iterator iter = skillRatings.iterator();
    	while (iter.hasNext()) {
    		SkillRating rating = (SkillRating)iter.next();
    		Skill ratingSkill = rating.getSkill();
    		if (ratingSkill != null) {
	    		Iterator branchIter = TreeHelper.getBranchCollection(skillToRemove).iterator();
	    		boolean done = false;
	    		while ((done == false) && (branchIter.hasNext())) {
	    			Skill branchSkill = (Skill)branchIter.next();
	    			String branchSkillCode = branchSkill.getCode();
	    			log.debug("clearSkillBranch() - looking at next skill in branch to see if matches current rating, skill = " 
	    					+ branchSkillCode);
	    			String ratingSkillCode = ratingSkill.getCode();
	    			if (branchSkillCode.equals(ratingSkillCode)) {
	    				log.debug("clearSkillBranch() - rating needs to be removed: " 
	    							+ ratingSkillCode);
	    				removeList.add(rating);
	    				done = true;
	    			}
	    		}
    		}
    		else {
    			log.debug("clearSkillBranch() ");
    		}
    	}
    	iter = removeList.iterator();
    	while (iter.hasNext()) {
    		SkillRating rating = (SkillRating)iter.next();
    		log.debug("removing skill: " + rating.getSkill().getCode());
    		skillRatings.remove(rating);
    	}
    }
    
    
    public void clearSkillBranches(Collection skillsToRemove) throws VectricsException {
    	Iterator iter = skillsToRemove.iterator();
    	while (iter.hasNext()) {
    		Skill skill = (Skill)iter.next();
    		clearSkillBranch(skill);
    	}
    	
    }
    
    
    public void removeSkillRating(Skill skill) {
    	SkillRating rating = findSkillRating(skill);
    	if (rating != null) {
    		skillRatings.remove(rating);
    	}
    }
    
    public SkillRating addRating(Skill skill) {
    	SkillRating skillRating = this.createSkillRating(skill);
    	if (skill.getScoringMethod() == null)
    		throw new SystemException("Skill scoring method is null, skill = " + skill.getDescription());
    	skillRating.setScoringMethod(skill.getScoringMethod());
    	skillRatings.add(skillRating);
    	return(skillRating);
    }

    public SkillRating addRating(Skill skill, String level) {
    	SkillRating skillRating = this.addRating(skill);
    	skillRating.setLevel(level);
    	return(skillRating);
    }

    public SkillRating addRating(String skillCode, String level) {
    	Skill skill = RecruitServiceLocator.getSkillProvider().findSkill(skillCode);
    	if (skill == null)
    		throw new SystemException("Attempt to add rating for non-existent skill: " + skill.getCode());
    	if (skill.getScoringMethod().getCode().equals(SkillScoringMethod.SCORING_METHOD_NONE))
    		throw new SystemException("Attempt to add rating for non-ratable skill: " + skill.getCode());
    	SkillRating skillRating = this.addRating(skill, level);
    	return(skillRating);
    }
    
    public void clearAllSkillRatings() {
    	skillRatings.clear();
    }
    
    public Set findAllSkillRatings() {
    	return(skillRatings);
    }
    
    public String toString() {
    	StringBuffer str = new StringBuffer();
		str.append("Skill Ratings:\r\n");
    	Iterator iter = skillRatings.iterator();
    	while (iter.hasNext()) {
    		SkillRating rating = (SkillRating)iter.next();
    		str.append("    <skill-rating skill=\"" + rating.getSkill().getCode() 
    				+ "\" level=" + rating.getLevel() + "/>\r\n");
    	}
    	return(str.toString());
    }
    


	public HashSet getSkillRatings() {
		return skillRatings;
	}

	/**
	 * @param skillRatings The skillRatings to set.
	 */
	public void setSkillRatings(HashSet skillRatings) {
		this.skillRatings = skillRatings;
	}

	/**
	 * @return Returns the evaluation.
	 */
	public UserEvaluation getEvaluation() {
		return evaluation;
	}
	/**
	 * @param evaluation The evaluation to set.
	 */
	public void setEvaluation(UserEvaluation evaluation) {
		this.evaluation = evaluation;
	}
	
}